package cn.tedu.luban.order.main.controller;

import cn.tedu.luban.order.common.enums.OrderResultEnum;
import cn.tedu.luban.order.common.enums.OrderStatusEnum;
import cn.tedu.luban.order.main.converter.OrderConverter;
import cn.tedu.luban.order.main.service.OrderService;
import cn.tedu.luban.order.protocol.VO.FrontOrderDetailVO;
import cn.tedu.luban.order.protocol.VO.FrontOrderItemVO;
import cn.tedu.luban.order.protocol.bo.OrderBO;
import cn.tedu.luban.order.protocol.param.OrderConfirmParam;
import cn.tedu.luban.order.protocol.param.OrderCreateParam;
import cn.tedu.luban.order.protocol.param.OrderFinishParam;
import cn.tedu.luban.order.protocol.param.OrderSignParam;
import cn.tedu.luban.order.protocol.query.FrontOrderListQuery;
import cn.tedu.luban.passport.protocol.jwt.UserPrinciple;
import cn.tedu.luban.passport.sdk.security.LubanSecurityContext;
import com.tedu.inn.protocol.ListRecordTotalBO;
import com.tedu.inn.protocol.exception.BusinessException;
import com.tedu.inn.protocol.model.Result;
import com.tedu.inn.protocol.pager.PagerResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderConverter orderConverter;

    /** 师傅抢单(创建工单)*/
    @PostMapping("/order/create")
    public Result<String> orderCreate(
            @RequestBody OrderCreateParam param) throws BusinessException {

        // 1. 频繁抢单的拦截 \ 补充userId
        reGrabIntercept(param);

        // 2.业务层调用
        String orderNo = orderService.orderCreate(param);

        return new Result<>(orderNo);
    }

    /**
     * 师傅登录查询 未完成的订单(分页)
     */
    @PostMapping("/order/list")
    public Result<PagerResult<FrontOrderItemVO>> orderList(
            @RequestBody FrontOrderListQuery query) throws BusinessException {

        Long userId = getUserId();
        query.setUserId(userId);

        ListRecordTotalBO<OrderBO> listBO = orderService.orderList(query);

        PagerResult<FrontOrderItemVO> pagerResult =
                orderConverter.assemblePagerResult(listBO, query);

        return new Result<>(pagerResult);
    }

    /**
     * 查询某个师傅的订单详情
     */
    @GetMapping("/order/info")
    public Result<FrontOrderDetailVO> orderDetail(String orderNo) throws BusinessException {

        OrderBO orderBO = orderService.orderDetail(orderNo);

        FrontOrderDetailVO vo = orderConverter.bo2frontDetailVO(orderBO);

        return new Result<>(vo);
    }

    /**
     * 师傅签到
     */
    @PostMapping("/order/sign")
    public Result<String> orderSign(@RequestBody OrderSignParam param) throws BusinessException {

        // 1.调用业务层,出现异常失败,没有异常则成功
        orderService.orderSign(param);

        // 2.正常返回数据(orderNo没有业务意义)
        return new Result<>(param.getOrderNo());
    }

    /**
     * 施工图片上传 \ 确认施工状态
     */
    @PostMapping("/order/confirm")
    public Result<String> orderConfirm(
            @RequestBody OrderConfirmParam param) throws BusinessException {
        // 1.调用业务层
        orderService.orderConfirm(param);

        // 2.正常结束 返回结果
        return new Result<>(param.getOrderNo());
    }


    public Long getUserId() throws BusinessException {
        // 获取登录用户
        UserPrinciple user = LubanSecurityContext.getLoginToken();
        // 判断用户是否登录
        if(user == null){
            throw new BusinessException("1000", "身份信息验证失败");
        }
        // 补充userId
        return user.getId();
    }


    // 想调用String类型数据incr做自增, 客户端template中value的序列化必须是String类型
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private void reGrabIntercept(OrderCreateParam param) throws BusinessException {

        // 补充userId
        Long userId = getUserId();
        param.setUserId(userId);

        String requestOrderNo = param.getRequestOrderNo();
        // 设计key值: "业务"+userId+requestOrderNo
        String reGrabLockKey = "luban:order:regrab:" + userId + ":" + requestOrderNo;

        // 对key值的incr操作,第一次是为1,连续争抢返回值>1
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        Long increment = opsForValue.increment(reGrabLockKey);
        stringRedisTemplate.expire(reGrabLockKey,3, TimeUnit.SECONDS);

        //返回值>1 连续争抢(频繁)
        if(increment>1){
            log.error("当前师傅:{},抢单:{},失败",userId,requestOrderNo);
            throw new BusinessException(OrderResultEnum.ORDER_RE_GRAB);
        }

    }


    /**
     * 师傅完成订单
     */
    @PostMapping("/order/finish")
    public Result<String> orderFinish(@RequestBody OrderFinishParam param) throws BusinessException{

        orderService.orderFinish(param);

        return new Result<>(param.getOrderNo());
    }



}
